<?php

namespace app\astrologer\controller\v5;

use app\astrologer\controller\AstrAuth;
use app\common\cachemodel\SystemConfig;
use app\common\lib\astrolog\Astrolog;
use app\common\lib\exception\ApiException;
use app\common\model\AstrologerSettingUser;
use app\common\model\AstroSettingUser1751;
use app\zyhsapi\model\ZyhsAstrTasks;
use app\zyhsapi\model\ZyhsUserQuestion;
use think\Log;
use think\response\Json;

class AstrolabeController extends AstrAuth
{
    /**
     * 档案id1 和 档案id2 的盘 的参数
     */
    const PARAMS_DOUBLE = ['composite_thirdprogressed', 'synastry', 'composite_progressions', 'davison', 'marks', 'synastry_thirdprogressed', 'synastry_progressions', 'davison_thirdprogressed', 'davison_progressions', 'marks_thirdprogressed', 'marks_progressions',];

    /**
     * 带档案id的盘
     */
    const PARAMS_SINGLE = ['natal', 'transits', 'thirdprogressed', 'thirdprogressedvsnatal', 'progressions', 'progressionsvsnatal', 'solar', 'solar_return', 'solar_returnvsnatal', 'lunar_return', 'lunar_returnvsnatal', 'firdaria', 'profection', 'fortune', 'zodrel', 'dodekatemorion', 'trimsamsa'];

    /**
     * 推运的盘，推运时间 datetime 和 时区timezone
     */
    const PARAMS_ADVANCE = ['now', 'transits', 'thirdprogressed', 'thirdprogressedvsnatal', 'progressions', 'progressionsvsnatal', 'solar', 'solar_return', 'solar_returnvsnatal', 'lunar_return', 'lunar_returnvsnatal', 'firdaria', 'profection', 'composite_thirdprogressed', 'composite_progressions', 'synastry_thirdprogressed', 'synastry_progressions', 'davison_thirdprogressed', 'davison_progressions', 'marks_thirdprogressed', 'marks_progressions',];

    /**
     * 合盘需要的所有参数，用于判断 两个档案是否反向
     */
    const PARAMS_SYNASTRY = ['synastry', 'synastry_thirdprogressed', 'synastry_progressions', 'composite', 'composite_thirdprogressed', 'composite_progressions', 'davison', 'davison_thirdprogressed', 'davison_progressions', 'marks', 'marks_thirdprogressed', 'marks_progressions', 'natal'];

    /**
     * 星盘设置需要使用
     */
    const DEFAULT_CONFIGURATION = [
        'planet' => [
            0 => [0, 0],
            1 => [0, 0],
            2 => [0, 0],
            3 => [0, 0],
            4 => [0, 0],
            5 => [0, 0],
            6 => [0, 0],
            7 => [0, 0],
            8 => [0, 0],
            9 => [0, 0],
            10 => [0, 0],
            11 => [0, 0],
            12 => [0, 0],
            13 => [0, 0],
            14 => [0, 0],
            15 => [0, 0],
            16 => [0, 0],
            17 => [0, 0],
            18 => [0, 0],
            19 => [0, 0],
            20 => [0, 0],
        ],
        'phase' => [
            0 => [0, 0],
            60 => [0, 0],
            90 => [0, 0],
            120 => [0, 0],
            180 => [0, 0],
            45 => [0, 0],
            135 => [0, 0],
            30 => [0, 0],
            150 => [0, 0],
            72 => [0, 0],
            144 => [0, 0],
            108 => [0, 0],
            36 => [0, 0],
        ],
        'arabic' => [
            0 => [0, 0],
            1 => [0, 0],
            2 => [0, 0],
            3 => [0, 0],
            4 => [0, 0],
            5 => [0, 0],
            6 => [0, 0],
            7 => [0, 0],
            8 => [0, 0],
            9 => [0, 0],
            10 => [0, 0],
            11 => [0, 0],
            12 => [0, 0],
            13 => [0, 0],
            14 => [0, 0],
            15 => [0, 0],
            16 => [0, 0],
            17 => [0, 0],
            18 => [0, 0],
            19 => [0, 0],
            20 => [0, 0],
            21 => [0, 0],
            22 => [0, 0],
            23 => [0, 0],
            24 => [0, 0],
            25 => [0, 0],
            26 => [0, 0],
        ],
        'h_sys' => 'p',
        'ecliptic' => 0,
        'zodrel' => 'p17',
        'firdaria' => 0,
        'profection_push_direction' => 0,
        'decanates' => 0,
        'bound_type' => 0,
        'ayanamsa' => 0,
        'location_use' => 0,
    ];

    /**
     * ---------- 仅【准有好事】端  问答 使用
     * 查看星盘-占星师后台回答问题、占星师后台考试简单题查看星盘
     * @param string    chart   需要请求的星盘
     * @param int       tid     星盘类型 [1-3] 现代 古典 特殊
     * @param int       qid     占星师回答的问题id
     * @param string       access_token     占星师后台的access_token
     * @return Json
     * @throws ApiException
     * @throws \Exception
     */
    public function questionAstrologer()
    {
        //检查参数
        $param = $this->request->param();
        $check = $this->checkParamAstro($param, true);
        if ($check !== true)
        {
            return show(config('code.error'), $check);
        }
        $astrInfo = $this->astrInfo;

        $taskInfo = (new ZyhsAstrTasks())->getInfoById($param['task_id']);
        $questionInfo = (new ZyhsUserQuestion())->getInfoById($taskInfo['qid']);
        if (!$questionInfo)
        {
            return show(config('code.error'), '问题不存在');
        }
        $record1 = '';
        $record2 = '';//用于合盘返回 ***$record2_name的UI
        if (isset($questionInfo['question_extend']['recode1']) && $questionInfo['question_extend']['recode1'])
        {
            $record1 = $questionInfo['question_extend']['recode1'];
        }
        if (isset($questionInfo['question_extend']['recode2']) && $questionInfo['question_extend']['recode2'])
        {
            $record2 = $questionInfo['question_extend']['recode2'];
        }
        //判断是否传了recode_index参数【只能是0或者1】
        if (isset($param['recode_index']))
        {
            if (0 === (int)$param['recode_index'])
            {
                $record1 = $questionInfo['question_extend']['recode1'];
            } else if (1 === (int)$param['recode_index'])
            {
                $record1 = $questionInfo['question_extend']['recode2'];
            } else
            {//传参异常
                return show(config('code.error'), 'recode_index 参数异常！');
            }
            $record2 = '';
        }
        //状态检查完成，开始实际业务
        $param['chart'] = (string)$param['chart'];
        $param['tid'] = (int)$param['tid'];
        $tid = 1;// 星盘配置方案使用默认值
        (isset($param['tid']) && in_array($param['tid'], [1, 2, 3], true)) && $tid = $param['tid'];
        //判断占星师是否绑定了app账户
        if ($astrInfo['uid'])
        {
            try
            {
                $settingData = (new AstroSettingUser1751())->getUserSettingByTid([
                    'uid' => $astrInfo['uid'],
                    'tid' => $tid,
                    'chart' => $param['chart'],
                ]);
            }
            catch (\Exception $e)
            {
                Log::write('获取token查看星盘，这里是：1.后台-》直播管理-》查看直播-》弹幕列表-》点击一个-》查看用户星盘；2.后台/主播管理员h5-》看盘详情；' . $param['access_token'] . ',error:' . $e->getMessage(), 'log', true);
                $settingData = (new AstroSettingUser1751())->getUserSettingByTid([
                    'uid' => 0,
                    'tid' => $tid,
                    'chart' => $param['chart'],
                ]);
            }
        } else
        {
            if (isset($astrInfo['id']))
            {
                try
                {
                    $settingData = (new AstrologerSettingUser())->getUserSettingByTid([
                        'uid' => $astrInfo['id'],
                        'tid' => $tid,
                        'chart' => $param['chart'],
                    ]);
                    if ($settingData['is_default'])
                    {
                        $settingData = (new AstroSettingUser1751())->getUserSettingByTid([
                            'uid' => 0,
                            'tid' => $tid,
                            'chart' => $param['chart'],
                        ]);
                    }
                }
                catch (\Exception $e)
                {
                    $settingData = (new AstroSettingUser1751())->getUserSettingByTid([
                        'uid' => 0,
                        'tid' => $tid,
                        'chart' => $param['chart'],
                    ]);
                }
            } else
            {
                Log::write('查看公共星盘错误，$astrInfo里的id为空！', 'error');
            }
        }

        $Astrolog = Astrolog::getInstance();

        //如果是合盘（星盘不会传is_recode_reverse参数），那么返回用户的昵称，用于显示 * in *
        if (isset($param['is_recode_reverse']) && (int)$param['is_recode_reverse'] === 1 && in_array($param['chart'], self::PARAMS_SYNASTRY))
        {
            if ($record2)
            {
                $Astrolog->setRecode1($record2);
            }
            if ($record1)
            {
                $Astrolog->setRecode2($record1);
            }
        } else
        {
            if ($record1)
            {
                $Astrolog->setRecode1($record1);
            }
            if ($record2)
            {
                $Astrolog->setRecode2($record2);
            }
        }

        if (isset($param['datetime']) && $param['datetime'] !== '')
        {
            $advanceTime = strtotime($param['datetime']);

            if ($advanceTime === false)
            {
                return show(config('code.error'), '时间格式异常');
            }

            [$year, $month, $day, $hour, $minute, $is_summer] = explode(',', date('Y,m,d,H,i,I', $advanceTime));

            $advanceInfo = [
                'year' => $year * 1,
                'month' => $month * 1,
                'day' => $day * 1,
                'hour' => $hour * 1,
                'minute' => $minute * 1,
                'timezone' => $param['timezone'] * 1,
                'is_summer' => $is_summer * 1,
            ];
            if (isset($param['longitude']))
            {
                $advanceInfo['longitude'] = $param['longitude'];
            }
            if (isset($param['latitude']))
            {
                $advanceInfo['latitude'] = $param['latitude'];
            }
            $Astrolog->setAdvance($advanceInfo);
        }
        $userSetting = [$param['chart'] => $settingData];
        // 法达参数数字转为字符串
        if (isset($userSetting[$param['chart']]['firdaria']))
        {
            if ($userSetting[$param['chart']]['firdaria'] === 0)
            {
                $userSetting[$param['chart']]['firdaria'] = 'default';
            } else
            {
                $userSetting[$param['chart']]['firdaria'] = 'another';
            }
        }
        // 界主星参数数字转为字符串
        if (isset($userSetting[$param['chart']]['bound_type']))
        {
            if ($userSetting[$param['chart']]['bound_type'] === 0)
            {
                $userSetting[$param['chart']]['bound_type'] = 'default';
            } else
            {
                $userSetting[$param['chart']]['bound_type'] = 'ptolemy_world';
            }
        }
        $data = $Astrolog->setExecPrefix(config('astrolog.prefix'))
            ->setIsAstrolabe(true)
            ->setUserSetting($userSetting)
            ->setVersion(2)
            ->setGetDatas([$param['chart']])
            ->getAstroDatas()
            ->getDatas($param['chart']);

        $error = $Astrolog->getError();
        if ($error)
        {
            Log::write('index:' . $error);

            return show(config('code.error'), $error);
        }

        if (in_array($param['chart'], ['now', 'natal', 'profection', 'firdaria', 'dodekatemorion', 'trimsamsa', 'zodrel', 'fortune']))
        {
            $data['extent_type'] = $settingData['bound_type'] ?? 0;
        }
        //  获取系统配置
        $config = (new SystemConfig())->getSystemConfig(['title1', 'title_intro1', 'title2', 'title_intro2']);
        if ($param['chart'] === 'natal')
        {
            $astro_config = config('astro');
            $data['icon_info'] = [
                'horoscope_name' => $astro_config['horoscope_name'],
                'divination_name' => $astro_config['divination_name'],
                'status' => $astro_config['status'],
            ];
            $data['natal_report_name'] = (isset($config['title1']) && !empty($config['title1'])) ? $config['title1'] : '';
        }

        //如果是合盘（星盘不会传is_recode_reverse参数），那么返回用户的昵称，用于显示 * in *
        if (isset($param['is_recode_reverse']) && in_array($param['chart'], self::PARAMS_SYNASTRY))
        {
            if ($record1 && isset($record1['name']))
            {
                $data['record1_name'] = $record1['name'];
            }

            if ($record2 && isset($record2['name']))
            {
                $data['record2_name'] = $record2['name'];
            }

        }
        return show(config('code.success'), '加载成功', $data);
    }

    /**
     * 验证客户端传递的参数是否正确【只有 占星师平台 和 天象盘】
     * @param array $param 参数
     * @param bool $is_astrologer 是否是占星师平台 true：占星师平台；false：天象盘
     * @return bool|string
     */
    private function checkParamAstro($param = [], $is_astrologer = false)
    {
        if (!isset($param['chart']) || !in_array($param['chart'], config('astroset175.chart'), true))
        {
            return '未知星盘';
        }

        if (!$is_astrologer)
        {// 天象盘验证
            if ($param['chart'] === 'now' && (!isset($param['longitude'], $param['latitude'])))
            {
                return '参数错误';
            }
            if (!isset($param['datetime']) || strtotime($param['datetime']) === false)
            {
                return '时间错误';
            }

            if (!isset($param['timezone']) || $param['timezone'] > 12 || $param['timezone'] < -12)
            {
                return '时区错误';
            }
        } else
        {//占星师平台验证
            if (!isset($param['task_id']))
            {
                return '缺少任务id';
            }
            // chart检测
            if (!in_array($param['chart'], self::PARAMS_SINGLE, true) && !in_array($param['chart'], self::PARAMS_DOUBLE, true) && !in_array($param['chart'], self::PARAMS_ADVANCE, true) && !in_array($param['chart'], self::PARAMS_SYNASTRY, true))
            {
                return 'chart参数错误';
            }
            // 推进盘验证
            if (in_array($param['chart'], self::PARAMS_ADVANCE, true))
            {
                if (!isset($param['datetime']) || strtotime($param['datetime']) === false)
                {
                    return '时间错误';
                }

                if (!isset($param['timezone']) || $param['timezone'] > 12 || $param['timezone'] < -12)
                {
                    return '时区错误';
                }
            }

        }

        return true;
    }
}
